package ucd.csi.comp30220.fall2011.oteop.airline.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Comparator;

import ucd.csi.comp30220.fall2011.oteop.airline.Airline;
import ucd.csi.comp30220.fall2011.oteop.airline.AirlineException;
import ucd.csi.comp30220.fall2011.oteop.airline.AirlineInfo;
import ucd.csi.comp30220.fall2011.oteop.flight.Flight;
import ucd.csi.comp30220.fall2011.oteop.flight.FlightException;
import ucd.csi.comp30220.fall2011.oteop.flight.FlightInfo;
import ucd.csi.comp30220.fall2011.oteop.flight.impl.LocalFlight;
import ucd.csi.comp30220.fall2011.oteop.flight.impl.RemoteFlightServer;
import ucd.csi.comp30220.fall2011.oteop.flughafen.Airport;
import ucd.csi.comp30220.fall2011.oteop.flughafen.AirportFinder;

public class AirlineImpl implements Airline {
   
    private static long ONE_MINUTE = 60*1000;
    
    private AirlineInfo info;
    private Thread thread;
    private Map<String,FlightSummary> summaries = new HashMap<String,FlightSummary>();
    
    private Set<FlightInfo> flights = new TreeSet<FlightInfo>(new Comparator<FlightInfo>() {
        public int compare(FlightInfo left, FlightInfo right) {
            return left.getDepartureDateTime().compareTo(right.getDepartureDateTime());
        }
    });
    
    public AirlineImpl(AirlineInfo info, FlightInfo[] flightInfos) {
        this.info = info;
        for (FlightInfo finfo : flightInfos) {
            flights.add(finfo);
            summaries.put(finfo.getNumber(), new FlightSummary());
        }
    }
    
    private void dispatch() {
        SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss:SSS");
        for (FlightInfo info: flights) {
            try {
               long sleep = info.getDepartureDateTime().getTime() - System.currentTimeMillis() - ONE_MINUTE;
               if (sleep > 0)
                   Thread.sleep(sleep);
            } catch (InterruptedException ie) {
               ie.printStackTrace();
            }
            try {
                new RemoteFlightServer(info);
                Airport airport = AirportFinder.find(info.getDepartureAirportInfo().getCode());
                if (airport != null)
                    airport.dispatchFlight(info);
                else 
                    System.err.println("Failed to send: " +info.getNumber() + " [ NO AIRPORT ]");
            } catch (Exception e) {
                System.err.println("Failed to send: " +info.getNumber() + " [" + e.getClass().getName() +"]");
                //e.printStackTrace();
            }
        }
    }
    
    public void start() {
        thread = new Thread(new Runnable() {
            public void run() {
                dispatch();
            }
        });
        thread.start();
    }

    public AirlineInfo getInfo() throws AirlineException {
        return info;
    }

    public void flightDeparted(String flightNumber, String airportCode, Date dateTime) throws AirlineException {
        summaries.get(flightNumber).setDepartureTime(dateTime);
    }

    public void flightLanded(String flightNumber, String airportCode, Date dateTime) throws AirlineException {
        summaries.get(flightNumber).setArrivalTime(dateTime);
    }
}
